package com.cskaoyan.app.wxservice.impl;

import com.cskaoyan.app.bean.bo.WxCouponBo;
import com.cskaoyan.app.bean.bo.adminbo.AdminListBo;
import com.cskaoyan.app.bean.common.CommonData;
import com.cskaoyan.app.bean.po.*;
import com.cskaoyan.app.bean.vo.wx.WxCouponSelectVo;
import com.cskaoyan.app.mapper.MarketCartMapper;
import com.cskaoyan.app.mapper.MarketCouponMapper;
import com.cskaoyan.app.mapper.MarketCouponUserMapper;
import com.cskaoyan.app.wxservice.WxCouponService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author kiggy
 * @since 2023/01/01 19:24
 */
@Service
public class WxCouponServiceImpl implements WxCouponService {

    @Autowired
    MarketCouponMapper couponMapper;

    @Autowired
    MarketCouponUserMapper userMapper;

    @Autowired
    MarketCartMapper cartMapper;

    /**
     * 从数据库market_coupon库中取出所有数据
     *
     * @param listBo：page，limit
     * @return
     */
    @Override
    @Transactional
    public CommonData listCoupon(AdminListBo listBo) {
        PageHelper.startPage(listBo.getPage(), listBo.getLimit());
        MarketCouponExample couponExample = new MarketCouponExample();
        couponExample.setOrderByClause("update_time desc");
        MarketCouponExample.Criteria criteria = couponExample.createCriteria();
        criteria.andDeletedEqualTo(false);
        List<MarketCoupon> marketCoupons = couponMapper.selectByExample(couponExample);
        PageInfo<MarketCoupon> couponPageInfo = new PageInfo<>(marketCoupons);
        CommonData<MarketCoupon> data = CommonData.data(couponPageInfo);
        return data;
    }

    /**
     * 从数据库market_coupon_user库中，通过userId取出用户的所有优惠券
     * status：0可以使用，1过期，2下架
     * 进入方法需要判断是否过期，更新status
     * @param listBo：page，limit，status
     * @return
     */
    @Override
    @Transactional
    public CommonData myListCoupon(AdminListBo listBo) {
        // 获得userId
        Subject subject = SecurityUtils.getSubject();
        Integer userId = (Integer) subject.getSession().getAttribute("userid");
        updateUserCouponStatus(userId);
        // 从coupon_user表中获得couponid
        PageHelper.startPage(listBo.getPage(), listBo.getLimit());
        MarketCouponUserExample userExample = new MarketCouponUserExample();
        MarketCouponUserExample.Criteria criteria = userExample.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andStatusEqualTo(listBo.getStatus());
        List<MarketCouponUser> couponUsers = userMapper.selectByExample(userExample);

        // 获得coupon
        Iterator<MarketCouponUser> iterator = couponUsers.iterator();
        List<MarketCoupon> coupons = new ArrayList<>();
        while (iterator.hasNext()) {
            MarketCouponUser couponUser = iterator.next();
            MarketCoupon coupon = couponMapper.selectByPrimaryKey(couponUser.getCouponId());
            coupons.add(coupon);
        }
        PageInfo<MarketCoupon> userPageInfo = new PageInfo<>(coupons);
        CommonData<MarketCoupon> data = CommonData.data(userPageInfo);
        return data;
    }

    /**
     * TODO:131,119
     * 在购物车结算时，展示可以使用的优惠券，通过商品总价格和优惠券的min判断
     * 在数据库market_coupon_user中通过userId和cartId取出优惠券
     *
     * @param couponBo：cartId，grouponRulesId，cartId=0表示有多条商品，否则表示的是购物车内商品id
     * @return
     */
    @Override
    @Transactional
    public CommonData selectList(WxCouponBo couponBo) {
        int cartId = couponBo.getCartId();
        // 获得userId
        Integer userId = (Integer) SecurityUtils.getSubject().getSession().getAttribute("userid");
        BigDecimal totalAmount = new BigDecimal(0);// 总价格
        if (cartId != 0) {
            // 获得总价
            MarketCart marketCart = cartMapper.selectByPrimaryKey(cartId);
            totalAmount = getTotalAmount(marketCart);
        } else {
            // cartId == 0
            MarketCartExample cartExample = new MarketCartExample();
            MarketCartExample.Criteria criteria = cartExample.createCriteria();
            criteria.andDeletedEqualTo(false);
            criteria.andUserIdEqualTo(userId);
            criteria.andCheckedEqualTo(true);
            List<MarketCart> cartList = cartMapper.selectByExample(cartExample);
            Iterator<MarketCart> iterator = cartList.iterator();
            while (iterator.hasNext()) {
                MarketCart cart = iterator.next();
                totalAmount = totalAmount.add(getTotalAmount(cart));
            }
        }
        // 查询可用coupon
        MarketCouponUserExample userExample = new MarketCouponUserExample();
        MarketCouponUserExample.Criteria criteria = userExample.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andStatusEqualTo((short) 0);
        criteria.andDeletedEqualTo(false);
        List<MarketCouponUser> couponUsers = userMapper.selectByExample(userExample);
        // 通过userCoupon查询coupon
        Iterator<MarketCouponUser> userIterator = couponUsers.iterator();
        ArrayList<Integer> integers = new ArrayList<>();
        while (userIterator.hasNext()) {
            MarketCouponUser couponUser = userIterator.next();
            Integer couponId = couponUser.getCouponId();
            integers.add(couponId);
        }
        MarketCouponExample couponExample = new MarketCouponExample();
        List<MarketCoupon> couponList = new ArrayList<>();
        for (int i = 0; i < integers.size(); i++) {
            MarketCouponExample.Criteria couponCriteria = couponExample.createCriteria();
            couponCriteria.andDeletedEqualTo(false);
            couponCriteria.andIdIn(integers);
            MarketCoupon marketCoupon = couponMapper.selectByPrimaryKey(integers.get(i));
            couponList.add(marketCoupon);
        }

        final BigDecimal total = totalAmount; // 为了避免报错：lambda 表达式中使用的变量应为 final 或有效 final
        List<MarketCoupon> couponCollect = couponList.stream()
                .filter(d->!d.getDeleted())
                .filter(d -> (total.compareTo(d.getMin())) >= 1)
                .collect(Collectors.toList());
        List<WxCouponSelectVo> selectVos = new ArrayList<>();
        Iterator<MarketCoupon> iterator = couponCollect.iterator();
        while (iterator.hasNext()) {
            MarketCoupon coupon = iterator.next();
            WxCouponSelectVo selectVo = new WxCouponSelectVo();
            selectVo.setAvailable(true);
            selectVo.setCid(coupon.getId());
            selectVo.setDesc(coupon.getDesc());
            selectVo.setDiscount(coupon.getDiscount());
            selectVo.setEndTime(coupon.getEndTime());
            selectVo.setId(0);
            selectVo.setMin(coupon.getMin());
            selectVo.setName(coupon.getName());
            selectVo.setStartTime(coupon.getStartTime());
            selectVo.setTag(coupon.getTag());
            selectVos.add(selectVo);
        }
        PageInfo<WxCouponSelectVo> couponPageInfo = new PageInfo<>(selectVos);
        CommonData<WxCouponSelectVo> data = CommonData.data(couponPageInfo);
        return data;
    }

    /**
     * 获得优惠券，如果无法获得，会显示740
     * 判断是否可以获取的条件：优惠券数量，限领数量，赠送类型是0，优惠券状态是0，
     * 0表示领取成功，740表示已领取，200表示无法领取
     * 即在数据库market_coupon中判断,获得后向market_coupon_user数据库中添加数据
     * user库：id，user_id，coupon_id，status，used_time，start_time，end_time，order_id，add_time，update_time，deleted
     *
     * @param couponId：couponId
     * @return
     */
    @Override
    @Transactional
    public Integer receiveCoupon(Integer couponId) {
        // 获得用户id，判断用户是否已经有了这个券
        Integer userid = (Integer) SecurityUtils.getSubject().getSession().getAttribute("userid");
        // 从coupon库中取优惠券
        MarketCouponExample couponExample = new MarketCouponExample();
        MarketCouponExample.Criteria couponCriteria = couponExample.createCriteria();
        couponCriteria.andIdEqualTo(couponId);
        couponCriteria.andStatusEqualTo((short) 0); // 校验status
        couponCriteria.andGoodsTypeEqualTo((short) 0); // 校验type
        couponCriteria.andTypeEqualTo((short) 0);
        couponCriteria.andTotalNotEqualTo(-1); // 校验优惠券数量
        List<MarketCoupon> coupons = couponMapper.selectByExample(couponExample);
        MarketCoupon coupon = null;
        if (coupons.size() != 0) {
            coupon = coupons.get(0);
        }
        if (coupon == null) {
            return 200;
        }

        // 校验限领数量
        if (coupon.getTotal() != 0) {
            if (!couponLimit(coupon)) {
                return 740;
            }
            ;
        }
        // 更新coupon表数据
        if (coupon.getTotal() != 0) {
            MarketCoupon marketCoupon = new MarketCoupon();
            int num = coupon.getTotal() - 1;
            // 0表示无限，所有如果优惠券被取完了，应设为-1
            if (num == 0) {
                num = -1;
            }
            marketCoupon.setTotal(num);
            MarketCouponExample.Criteria couponExampleCriteria = couponExample.createCriteria();
            couponExampleCriteria.andIdEqualTo(couponId);
            couponMapper.updateByExampleSelective(marketCoupon, couponExample);
        }
        // 向数据库添加数据
        // user库：id，user_id，coupon_id，status，used_time，start_time，end_time，order_id，add_time，update_time，deleted
        MarketCouponUser couponUser = new MarketCouponUser();
        couponUser.setUserId(userid);
        couponUser.setCouponId(couponId);
        couponUser.setStatus((short) 0);
        couponUser.setUsedTime(null);
        // 如果是1，基于优惠券时间
        if (coupon.getTimeType()==1){
            couponUser.setStartTime(coupon.getStartTime());
            couponUser.setEndTime(coupon.getEndTime());
        }else {
            // 基于领取和有效期的相对时间
            Short days = coupon.getDays();
            Calendar calendar = Calendar.getInstance(); // 获取Calendar实例
            calendar.setTime(new Date()); // 设置当前日期
            calendar.add(Calendar.DATE, days); // 加8天
            Date endTime = calendar.getTime(); // 获取新日期
            couponUser.setStartTime(new Date());
            couponUser.setEndTime(endTime);
        }
        couponUser.setAddTime(new Date());
        couponUser.setUpdateTime(new Date());
        couponUser.setDeleted(false);
        userMapper.insertSelective(couponUser);
        return 0;
    }

    /**
     * 在coupon数据库中通过code和优惠券数量判断能否获得优惠券(判断)
     * 添加
     * 可以获得需要修改优惠券数量
     * 742：无法领取，0：领取成功, 200:已领取
     * 需要判断当前优惠券是否可用领取：是否已领取，是否存在
     *
     * @param couponBo:code
     * @return
     */
    @Override
    @Transactional
    public Integer exchangeCoupon(WxCouponBo couponBo) {
        // 获得用户id，
        Integer userid = (Integer) SecurityUtils.getSubject().getSession().getAttribute("userid");

        MarketCouponExample couponExample = new MarketCouponExample();
        MarketCouponExample.Criteria criteria = couponExample.createCriteria();
        criteria.andStatusEqualTo((short) 0);
        criteria.andGoodsTypeEqualTo((short) 0);
        criteria.andDeletedEqualTo(false);
        criteria.andTypeEqualTo((short) 2);
        criteria.andTotalNotEqualTo(-1);
        criteria.andCodeEqualTo(couponBo.getCode());
        List<MarketCoupon> coupons = couponMapper.selectByExample(couponExample);
        MarketCoupon coupon = null;
        if (coupons.size() != 0) {
            coupon = coupons.get(0);
        }
        // 没取到
        if (coupon == null) {
            return 742;
        }
        // 校验是否已领取
        if (coupon.getLimit() != 0) {
            if (!couponLimit(coupon)) {
                return 200;
            }
        }
        // 添加
        MarketCouponUser couponUser = new MarketCouponUser();
        couponUser.setUserId(userid);
        couponUser.setCouponId(coupon.getId());
        couponUser.setStatus((short) 0);
        couponUser.setUsedTime(null);
        couponUser.setStartTime(coupon.getStartTime());
        couponUser.setEndTime(coupon.getEndTime());
        couponUser.setAddTime(new Date());
        couponUser.setUpdateTime(new Date());
        couponUser.setDeleted(false);
        userMapper.insertSelective(couponUser);

        // 取出后需要更新优惠券数量
        if (coupon.getTotal() != 0) {
            MarketCoupon marketCoupon = new MarketCoupon();
            int num = coupon.getTotal() - 1;
            // 0表示无限，所有如果优惠券被取完了，应设为-1
            if (num == 0) {
                num = -1;
            }
            marketCoupon.setTotal(num);
            MarketCouponExample.Criteria couponExampleCriteria = couponExample.createCriteria();
            couponExampleCriteria.andIdEqualTo(coupon.getId());
            couponMapper.updateByExampleSelective(marketCoupon, couponExample);
        }
        return 0;
    }

    /**
     * 在进入list方法时更新userCoupon中的status
     * @param userId
     */
    private void updateUserCouponStatus(Integer userId) {
        MarketCouponUserExample userExample = new MarketCouponUserExample();
        MarketCouponUserExample.Criteria criteria = userExample.createCriteria();
        criteria.andUserIdEqualTo(userId);
        List<MarketCouponUser> couponUsers = userMapper.selectByExample(userExample);
        if (couponUsers.size()==0){
            return;
        }
        for (int i = 0; i < couponUsers.size(); i++) {
            Date startTime = couponUsers.get(i).getStartTime();
            // 没有startTime直接返回不更新
            if (startTime==null){
                continue;
            }
            Date endTime = couponUsers.get(i).getEndTime();
            Integer id = couponUsers.get(i).getId();
            MarketCouponUser coupon = new MarketCouponUser();
            // 过期
            if ((startTime.compareTo(endTime)==1)){
                coupon.setId(id);
                coupon.setStatus((short) 2);
                userMapper.updateByPrimaryKeySelective(coupon);
            }
        }
    }

    /**
     * 获得购物车的总价钱
     *
     * @param marketCart
     * @return
     */
    private static BigDecimal getTotalAmount(MarketCart marketCart) {
        BigDecimal singlePrice;
        int cartNum;
        BigDecimal totalAmount;
        singlePrice = marketCart.getPrice();
        cartNum = marketCart.getNumber();
        totalAmount = singlePrice.multiply(BigDecimal.valueOf(cartNum));
        return totalAmount;
    }

    /**
     * 判断限领
     *
     * @param coupon
     * @return
     */
    private boolean couponLimit(MarketCoupon coupon) {
        MarketCouponUserExample userExample = new MarketCouponUserExample();
        MarketCouponUserExample.Criteria criteria = userExample.createCriteria();
        criteria.andCouponIdEqualTo(coupon.getId());
        List<MarketCouponUser> userCoupon = userMapper.selectByExample(userExample);
        if (userCoupon != null && userCoupon.size() >= coupon.getTotal()) {
            return false;
        } else {
            return true;
        }
    }
}
